/**
 * PoolThread.java Create on 2012-4-10     
 *      
 * Copyright (c) 2012-4-10 by yiming     
 *      
 * @author <a href="alenzhangym@hotmail.com">Yiming</a>     
 * @version 1.0 
 */
package com.yimi.taskmanager;

import android.util.Log;

import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * TODO 功能描述
 * 
 * 线程池，提高服务端并发性。
 * 
 * @author Yiming
 * @version 1.0
 */
public class ThreadPool {
	private static ThreadPool instance = ThreadPool.getInstance();
	public PoolWorker[] workers;
	boolean debug;
	private int worker_num = 0;
	private int taskCounter = 0;
	private static List<Task> taskQueue = Collections
			.synchronizedList(new LinkedList<Task>());
	
	public ThreadPool() {
	    workers = new PoolWorker[4];
		for (int i = 0; i < workers.length; i++) {
			workers[i] = new PoolWorker(i);
		}
	}

	private ThreadPool(int pool_worker_num) {
		worker_num = pool_worker_num;
		workers = new PoolWorker[worker_num];
		for (int i = 0; i < workers.length; i++) {
			workers[i] = new PoolWorker(i);
		}
	}

	public void addTask(Task newTask) {
		synchronized (taskQueue) {
			newTask.setTaskId(++taskCounter);
			newTask.setSubmitTime(new Date());
			taskQueue.add(newTask);
			/* 唤醒队列, 开始执行 */
			taskQueue.notifyAll();
		}
		Log.i("ThreadPool", "Submit Task<" + newTask.getTaskId() + ">: "
				+ newTask.info());
	}
	
	public void cacelTask(Task newTask){
	    synchronized (taskQueue) {
	        if(taskQueue.contains(newTask)){
	            taskQueue.remove(newTask);
	        } 
	    }
	}

	public void cancelTask(String command){
	    synchronized (taskQueue) {
	        for(int i=0;i<taskQueue.size();i++){
	          Task task= taskQueue.get(i);
	          if(task.getTaskCommand().equals(command)){
	              taskQueue.remove(task);
	              return;
	          }
	        }
	    }
	}
	
	/**
	 * 销毁线程池
	 */
	public synchronized void destroy() {
		for (int i = 0; i < worker_num; i++) {
			workers[i].stopWorker();
			workers[i] = null;
		}
		taskQueue.clear();
	}

	public static synchronized ThreadPool getInstance() {
		if (instance == null)
			return new ThreadPool();
		return instance;
	}

	/**
	 * 池中工作线程
	 * 
	 * @author Yiming
	 * @version 1.0
	 */
	private class PoolWorker extends Thread {
		private int index = -1;
		/* 该工作线程是否有效 */
		private boolean isRunning = true;
		/* 该工作线程是否可以执行新任务 */
		private boolean isWaiting = true;

		public PoolWorker(int index) {
			this.index = index;
			start();
		}

		public void stopWorker() {
			this.isRunning = false;
		}

		public boolean isWaiting() {
			return this.isWaiting;
		}

		/**
		 * 循环执行任务 
		 */
		public void run() {
			while (isRunning) {
				Task r = null;
				synchronized (taskQueue) {
					while (taskQueue.isEmpty()) {
						try {
							/* 任务队列为空，则等待有新任务加入从而被唤醒 */
							taskQueue.wait(20);
						} catch (InterruptedException ie) {
							Log.e(getName(), ie.toString());
						}
					}
					/* 取出任务执行 */
					r = (Task) taskQueue.remove(0);
				}
				if (r != null) {
					isWaiting = false;
					try {
						if (debug) {
							r.setBeginExceuteTime(new Date());
							Log.i("ThreadPool", "Worker<" + index
									+ "> start execute Task<" + r.getTaskId()
									+ ">");

							if (r.getBeginExceuteTime().getTime()
									- r.getSubmitTime().getTime() > 1000)
								Log.i("ThreadPool",
										"longer waiting time. "
												+ r.info()
												+ ",<"
												+ index
												+ ">,time:"
												+ (r.getFinishTime().getTime() - r
														.getBeginExceuteTime()
														.getTime()));
						}
						/* 该任务是否需要立即执行 */
						if (r.needExecuteImmediate()) {
							new Thread(r).start();
						} else {
							r.run();
						}
						if (debug) {
							r.setFinishTime(new Date());
							Log.i("ThreadPool", "Worker<" + index
									+ "> finish task<" + r.getTaskId() + ">");
							if (r.getFinishTime().getTime()
									- r.getBeginExceuteTime().getTime() > 1000)
								Log.i("ThreadPool", "longer execution time. "
										+ r.info()
										+ ",<"
										+ index
										+ ">,time:"
										+ (r.getFinishTime().getTime() - r
												.getBeginExceuteTime()
												.getTime()));
						}
					} catch (Exception e) {
						e.printStackTrace();
						Log.e("ThreadPool", e.getMessage());
					}
					isWaiting = true;
					r = null;
				}
			}
		}
	}
}